import {
  forwardRef,
  useImperativeHandle,
  useCallback,
  ReactElement,
  useState,
  useMemo,
  useEffect,
  useRef,
  Ref,
} from 'react';
import { Popup, Checkbox, Radio, InfiniteScroll } from 'antd-mobile';
import EformSelectInput from '../../../EformStaticList/designer/wapServer/EformSelectInput';
import EformSelectList from '../../../EformStaticList/designer/wapServer/EformSelectList';
import useListRequest from '../../designer/wapServer/useListRequest';
import { multilingualFormat, useEvents } from '@inbiz/utils';
import { connect, mapProps } from '@formily/react';
import { defaultProps } from '../../designer/schema';
import { getTableInfo, getTableInfoApi } from '../../designer/webServer/services';
import api from './api';
import './index.less';
import { getMessage, TextWidget } from '@inbiz/react';
import { InbizIcon } from '@inbiz/utils';
import noData from './noData.svg'
import { useInbizData, requestInbizData } from '@inbiz/hooks';

type Iprops = {
  value?: string;
  lang: string;
  isTpl: boolean;
  inbiz: {
    browser: {
      designer: boolean;
    };
    appInfo: {
      appId: string;
    };
  };
  selecttype: boolean;
  appId: string;
  sourcetype?: string;
  sourceModel?: string;
  primarykey?: string;
  onChange: Function;
  readOnly: boolean;
  disabled: boolean;
  autoLoading: boolean;
  search: boolean;
  searchField: any;
  showconfig: {
    storageField?: string;
  };
  modelname: string;
  viewMode?: string;
  defaultValue:any;
  emit?: {
    /** 内容改变时触发 */
    (type: 'onChange', value?: string): void;
    /**下拉模式下 弹出框选择时触发 */
    (type: 'onSelect', value?: string): void;
    (type: 'onload'): void;
    (type: 'onSuccess', arg: { list: any[]; total: number }): void;
    (type: 'onError'): void;
  };
  callBackEvents: {
    onParamFormat?: <T>(param: T) => T;
    onData?: <T>(data: T) => T;
    onRequest?: (parm: any) => Promise<any>;
    onTextParamFormat?: (parm: any) => Promise<any>;
    onTextRequest?: (parm: any) => Promise<any>;
    onTextData?: (parm: any) => Promise<any>;
  };
};

type ref = Ref<ReturnType<typeof api> & { isValid: () => boolean }>;

const EformDynamicList = forwardRef((props: Iprops, ref: ref): ReactElement => {
  const [configEvents] = useEvents(props.callBackEvents, props.emit);
  const appId = props.inbiz.appInfo.appId;
  const [events] = useEvents(props.callBackEvents, props.emit);
  const [state, $state] = useState<any>({
    ...props,
    value: '',
    checkList: '',
    clickNum: 0,
    autoLoading: props.autoLoading,
  });
  // 初始化判断变量
  const [num, $num] = useState(0);
  // 保存所有加载的数据
  const [listData, $listData
  ] = useState<{
    total: number;
    pageIndex: number;
    searchValue?: string;
    list: {
      [key: string]: string | number | boolean;
    }[];
  }>({
    list: [],
    pageIndex: 0,
    total: 0,
  });

  // 选中展示option(json字符串item)
  const [valueJson, $valueJson] = useState<any[]>([]);
  // 列表弹层显示
  const [popupVisible, $popupVisible] = useState(false);
  const $loading = useRef<Boolean>(false);

  // 兼容老版查询sourceModel
  const searchSourceModel = useMemo(() => {
    if (!state?.sourceModel) return;
    if (typeof state.sourceModel === 'string') {
      return state.sourceModel
    }
    if ('searchData' in state.sourceModel) {
      return state.sourceModel.searchData
    }
  }, [state]);

  // 兼容老版编辑sourceModel
  const editSourceModel = useMemo(() => {
    if (!state?.sourceModel) return;
    if (typeof state.sourceModel === 'string') {
      return state.sourceModel
    }
    if ('editData' in state.sourceModel) {
      return state.sourceModel.editData
    }
  }, [state]);

  // 数据加载 以及更新
  const { runAsync, error, loading } = useInbizData(
    () => {
      if (props.sourcetype === 'model') {
        return { modelkey: searchSourceModel! };
      } else {
        if (typeof searchSourceModel === 'object') {
          return searchSourceModel;
        } else {
          return { modelkey: searchSourceModel! };
        }
      }
    },
    {
      configEvents: events
    }
  );

  // 编辑获取数据详情
  const { runAsync: editRunAsync } = useInbizData(
    () => {
      if (props.sourcetype === 'model') {
        return {
          service: ({
            appId,
            ...params
          }) => {
            return getTableInfo({
              appId,
              ...params
            });
          },
        };
      } else {
        if (typeof editSourceModel === 'string') {
          return {
            service: ({
              appId,
              ...params
            }) => {
              return getTableInfoApi({
                appId,
                ...params
              });
            },
          };
        } else {
          return editSourceModel;
        }
      }
    },
    {
      eventKeys: ['onTextParamFormat', 'onTextRequest', 'onTextData'],
      configEvents
    }
  );

  $loading.current = loading;
  // 是否内部触发onChange
  const usChange = useRef<boolean>(false);
  // 记录多选时，选中数据的详情。解决选中数据后，查询后再次选中其他数据，查询前选中的数据不显示
  const selectData = useRef<any[]>([]);
  //存储字段
  const storageField = props.showconfig?.storageField || props.primarykey || 'id';
  const [text, $text] = useState()
  const {
    readOnly, // 只读
    labelDirection,
    selecttype, //选择方式    false单选    true多选
    selectWindowHeight,
  } = state;

  useImperativeHandle(
    ref,
    () => {
      return {
        //@ts-ignore
        ...api(
          configEvents,
          {
            state,
            listData,
            $listData,
            props,
            valueJson,
            storageField,
            selectData: selectData.current
          }
        ),
      };
    },
    [state, listData, storageField, valueJson],
  );
  // 筛选默认值 当没有返回默认值的时候 清空该默认值
  useEffect(() => {
    if (usChange.current) {
      usChange.current = false;
      return;
    }
    if (props.value && (props.value !== '' || (Array.isArray(props.value) && props.value.length))) {
      setValueMethod(props.value);
    } else {
      $state({
        ...state,
        value: props.selecttype ? [] : '',
        checkList: props.selecttype ? [] : '',
      });
      $valueJson([]);
    }
  }, [props.value]);
  // 过滤html标签
  const removeHtmlTag = (str: string) => {
    if (!str && Number(str) != 0) return '';
    try {
      str = str
        .replace(/<\/?[^>]*>/g, '')
        .replace(/[ | ]*\n/g, '\n')
        .replace(/\n[\s| | ]*\r/g, '\n')
        .replace(/&nbsp;/gi, '')
        .replace(/\r\n/gi, '')
        .replace(/\n/gi, '');
      return str;
    } catch (ex) {
      return str;
    }
  };

  const getSearchValue = (str, value) => {
    let result = value;
    const index = str.toLowerCase().indexOf(value.toLowerCase())
    if (index > -1) {
      result = str.substr(index, value.length)
    }
    return result;
  }
  // 获取数据方法
  const getData = useCallback(
    async ({
      pageIndex = 1,
      searchValue,
      list,
    }: { pageIndex?: number; searchValue?: string; list?: [] } = {}) => {

      if (searchSourceModel && appId) {
        $listData((data) => {
          return {
            ...data,
            pageIndex,
            searchValue,
            list: list || data.list,
          }
        });
        let index = 0;
        let data =
          props.sourcetype === 'api'
            ? {
              appId: appId,
              key: searchSourceModel,
              iConditions: {
                pageIndex,
                pageSize: state.showconfig?.pageSize || 10,
                search: listData.searchValue,
                searchField: state.searchField,
                modelName: props.modelname
              },
              pageInfo: {
                index: pageIndex,
                size: state.showconfig?.pageSize || 10,
              }
            }
            : {
              appId: appId,
              key: searchSourceModel,
              pageInfo: {
                index: pageIndex,
                size: state.showconfig?.pageSize || 10,
              },
              conditions: searchValue
                ? [{
                  index,
                  connector: 'and',
                  condition: state.searchField?.map((item: string) => ({
                    connector: 'or',
                    operator: 'like',
                    //@ts-ignore
                    field: item,
                    value: searchValue,
                    modelName: item.includes('$') ? item.split('$')[0] : props.modelname
                  })) || [],
                }] : [],
            };
        if (typeof searchSourceModel == 'object') {
          data = { ...data.iConditions };
        }
        return runAsync(data)
          .then((data) => {
            if (data?.Rows.length) {
              data.Rows.forEach(item => {
                Object.keys(item).forEach(key => {
                  item[key] = multilingualFormat(item[key])
                });
              });
            }
            if (data === null) {
              // 请求失败时， 不继续请求
              $listData((listData) => {
                return {
                  ...listData,
                  list: [...listData.list],
                  total: -1
                };
              })
            }
            if (data?.Rows) {
              pageIndex > 1
                ? //@ts-ignore
                $listData((listData) => {
                  let dataList = {
                    ...listData,
                    total: data.Total,
                    list: [...listData.list, ...data.Rows],
                  };
                  props.emit?.('onSuccess', dataList);
                  return dataList;
                })
                : //@ts-ignore
                $listData((listData) => {
                  let dataList = {
                    ...listData,
                    total: data.Total,
                    list: [...data.Rows],
                  };
                  props.emit?.('onSuccess', dataList);
                  return dataList;
                });
            }
            else {
              $listData((listData) => {
                return {
                  ...listData,
                  list: [],
                  total: 0
                };
              })
            }

          })
          .catch(() => {
            props.emit?.('onError');
          });
      } else {
        return Promise.resolve();
      }
    },
    [searchSourceModel, appId, state.showconfig, listData.searchValue],
  );


  // 暴露出去的setValue 方法
  const setValueMethod = async (value: any, isRequst?: boolean) => {
    if (value) {
      value = value.toString();
    }
    let list: any;
    if (value.indexOf(',') !== -1 && selecttype) {
      list = value.split(',');
    } else if (value.indexOf('，') !== -1 && selecttype) {
      list = value.split('，');
    } else if (!selecttype && (value.indexOf(',') !== -1 || value.indexOf('，') !== -1)) {
      list = '';
    } else if (selecttype && value.indexOf(',') == -1) {
      list = value ? [value] : [];
    } else {
      list = value;
    }
    // 需要走请求接口
    if (!isRequst && list.toString().length) {
      let params: any =
        props.sourcetype === 'api'
          ? {
            appId: appId || '',
            id: value,
            key: editSourceModel || '',
            iConditions: {},
          }
          : {
            appId: appId || '',
            ids: value,
            queryKey: editSourceModel || '',
            field: storageField,
          };
      if (typeof editSourceModel == 'object') {
        params = {
          id: value
        }
      }
      // 接口合法验证l
      const data: any = await editRunAsync(params);
      if (data && !Array.isArray(data.Rows)) {
        data.Rows = [data.Rows];
      }
      if (data?.Rows?.length) {
        data.Rows.forEach(item => {
          Object.keys(item).forEach(key => {
            item[key] = multilingualFormat(item[key])
          });
        })
      }
      if (data && Array.isArray(data.Rows) && data.Rows.length) {
        if (data?.Rows) {
          let param: any[] = [];
          let value: any[] = [];
          let checkList: any[] = [];
          data.UniqueId &&
            data.Rows.map((item: any) => {
              if (!item[storageField]) {
                item[storageField] = item[data.UniqueId];
              }
            });
          data.Rows.forEach((item: any) => {
            param.push(JSON.stringify(item));
            value.push(item[storageField]);
            checkList.push(item[storageField]);
          });
          selectData.current = data.Rows
          $valueJson(param);
          $state({
            ...state,
            value: props.selecttype ? value : value[0],
            checkList: props.selecttype ? checkList : checkList[0],
          });
        }
      } else {
        $state({
          ...state,
          value: props.selecttype ? [] : '',
          checkList: props.selecttype ? [] : '',
        });
        $valueJson([]);
      }
      props.emit?.('onload');
    } else if (isRequst && list.toString().length) {
      // 重置方法 不需要走请求直接查找
      if (!selecttype) {
        listData.list.forEach((item) => {
          if (item?.[storageField] == list) {
            $state((state: any) => ({ ...state, value: JSON.stringify(item) }));
          }
        });
      } else {
        let newValue: any = [];
        list.forEach((item: any) => {
          listData.list.forEach((item1) => {
            if (item == item1?.[storageField]) {
              newValue.push(JSON.stringify(item1));
            }
          });
        });
        $state((state: any) => ({ ...state, value: newValue }));
      }
    } else {
      $state((state: any) => ({ ...state, value: list }));
    }
  };

  //加载更多
  const loadMore = useCallback(() => {
    if ($loading.current) {
      return new Promise(resolve => {
        const inter = setInterval(() => {
          if ($loading.current === false) {
            clearInterval(inter)
            resolve();
          }
        }, 50)
      })
    } else {
      return getData({ pageIndex: listData.pageIndex + 1, searchValue: listData.searchValue });
    }

  }, [listData.pageIndex, listData.searchValue]);

  // 显示字段格式化
  const showData = useMemo(() => {
    if (state.showconfig?.list?.length) {
      return state.showconfig?.list.map((item: any) => {
        item.Value = item.Value.replace('.', '$');
        return item as { YsField: string; Value: string };
      });
    } else {
      return [];
    }
  }, [state.showconfig, state.queryData]);

  // 单选
  const SingleSelectBox = ({ numberChange }: { numberChange: (n: number) => void }) => {
    return (
      <div className="selectList"  >
        <Radio.Group
          defaultValue={state.checkList}
          // value={state.checkList}
          onChange={(val) => {
            const data = listData.list.find(el => el?.[storageField] === val);
            selectData.current = [data];
            $state({ ...state, checkList: val });
            //@ts-ignore
            props.emit?.('onSelect', val, listData.list);
          }}
        >
          {listData.list.map((item: any, index: number) => {
            return (
              <div className="EformDynamicListcard" key={item.key}>
                {renderItem(item, index, showData)}
                <Radio className="poupRadio" key={index} value={item?.[storageField]}></Radio>
              </div>
            );
          })}
        </Radio.Group>

        <InfiniteScroll
          loadMore={loadMore}
          hasMore={error ? false : (loading && listData.pageIndex === 1) || listData.list.length < listData.total || listData.pageIndex === 0}
        />
      </div>
    );
  };

  // 多选
  const MultipleSelectBox = ({ numberChange }: { numberChange: (n: number) => void }) => {
    return (
      <div className="selectList" >
        <Checkbox.Group
          //@ts-ignore
          defaultValue={state.checkList}
          onChange={(val) => {
            selectData.current = selectData?.current?.filter(item => val.includes(item?.[storageField]));
            val.forEach(v => {
              const isHas = selectData?.current?.some(item => item?.[storageField] === v);
              if (!isHas) {
                const item = listData.list.find(el => el?.[storageField] === v);
                selectData.current.push(item);
              }
            });
            $state({ ...state, checkList: val });
            //@ts-ignore
            props.emit?.('onSelect', val, listData.list);
            numberChange(val.length);
          }}
        >
          {listData.list.map((item: any, index: number) => {
            return (
              <div className="EformDynamicListcard" key={item.key}>
                {renderItem(item, index, showData)}
                <Checkbox className="poupRadio" value={item?.[storageField]}></Checkbox>
              </div>
            );
          })}
        </Checkbox.Group>

        <InfiniteScroll
          loadMore={loadMore}
          hasMore={error ? false : (loading && listData.pageIndex === 1) || listData.list.length < listData.total || listData.pageIndex === 0}
        />
      </div>
    );
  };

  // 渲染单个卡片
  const renderItem = (data: any, dataIndex: number, showfild: any) => {
    const newData = { ...data };

    if (listData.searchValue) {
      props.searchField.forEach((key: string) => {
        if ((newData?.[key] != undefined) && data?.[key].toString().toLowerCase().includes(listData.searchValue.toLowerCase())) {
          newData[key] = data?.[key].toString().toLowerCase().replaceAll(listData.searchValue.toLowerCase(), `<span class='heightLight'>${getSearchValue(data[key].toString(), listData.searchValue.toLowerCase())}</span>`)
        }
      })
    }
    return (
      <div key={'card' + dataIndex}>
        {' '}
        {showfild.map((item: any, index: number) => {
          return (
            <div key={'cardItem' + index} className="cardItem">
              <div className="itemTitle">
                {item.Text && item.Text !== '' ? getMessage(item.Text) : item.Value}：
              </div>
              <div className="itemValue" dangerouslySetInnerHTML={{
                __html
                  : newData?.[item.Value]
              }}>
              </div>
            </div>
          );
        })}
      </div>
    );
  };

  const handleSearch = useCallback((value: any) => {
    $listData(old => ({
      ...old,
      pageIndex: 0,
      searchValue: value,
      list: []
    }))

  }, [listData.searchValue])

  // 下拉面板
  const Popupa = useMemo(() => {
    return (
      <EformSelectList
        value={state.value}
        selectWindowHeight={selectWindowHeight}
        contentHeight={'94%'}
        type={selecttype}
        confirm={() => {
          $popupVisible(false);
          let newCheckList = props.selecttype ? state.checkList : [state.checkList];
          const selectList = selecttype ? selectData.current : listData?.list;
          let list =
            selectList
              ?.filter((item) => newCheckList.includes(item?.[storageField]))
              .map((item) =>
                JSON.stringify(item)
              ) || [];

          $state({ ...state, value: state.checkList });
          usChange.current = true;
          props.onChange(state.checkList);
          if (selecttype) {
            $valueJson(oldList => {
              return [...new Set([...oldList, ...list].map(item => typeof item === 'string' ? item : JSON.stringify(item)).filter(item => {
                const data = JSON.parse(item);
                return state.checkList.includes(data?.[storageField])
              }))]
            });
          } else {
            $valueJson(list)
          }

        }}
        cancel={() => {
          $popupVisible(false);
          handleSearch('')
          if (state.checkList && state.value) {
            $state({ ...state, checkList: state.value })
          } else {
            $state({ ...state, checkList: '' })
          }
        }}
        children={
          (!searchSourceModel || !loading && listData.list.length == 0 && listData.pageIndex >= 1) ? () => <div className='noResult'><InbizIcon type="icon-ic-zanwushuju" style={{ fontSize: 50 }} /><p >暂无数据</p></div> :
            (selecttype
              ? (numberChange) => <MultipleSelectBox numberChange={numberChange} />
              : (numberChange) => <SingleSelectBox numberChange={numberChange} />
            )
        }
        search={props.search}
        searchField={props.searchField}
        listData={listData}
        onSearch={handleSearch}
        checkList={state.checkList}
        popupVisible={popupVisible}
      />
    );
  }, [listData.list, state.value, state.showconfig, state.autoLoading, state.checkList, loading, searchSourceModel]);
  // tags的移除事件
  const remove = (e: any, item: any, fieldId: string, showValue: any, recentValue: any) => {
    e.stopPropagation();
    if (!selecttype) {
      $state((state: any) => ({ ...state, value: '', checkList: '' }));
      props.onChange('');
      $valueJson([]);
    } else {

      let newValue: any[];
      //@ts-ignore
      newValue = state.value.filter((valueItem: any) => {
        return valueItem != item[fieldId];
      });
      $state({ ...state, value: newValue, checkList: newValue });

      usChange.current = true;
      let list = showValue.filter((item: any) => {
        return newValue.includes(item[storageField])
      }).map((it: any) => JSON.stringify(it))
      props.onChange(newValue);
      $valueJson(list)
    }
  };
  // 打开list抽屉
  const openPopup = useCallback(() => {
    if (!props.readOnly && !props.inbiz.browser.designer) {
      if (state.clickNum == 0 && state.autoLoading) {
        handleSearch('')
        $state((state: any) => ({ ...state, clickNum: 1 }));
      }
      $popupVisible(true)
      handleSearch('')
    }
  }, [props.readOnly, state, props.inbiz.browser.designer]);
  useEffect(() => {
    $text(ref?.current?.getText?.() || state.checkList)
  }, [state.value])
  return (
    <>{
      props.viewMode == 'look' ? <div style={{ lineHeight: '31.5px',fontSize:'16px' }}>{text}</div> :
        <>
          <EformSelectInput
            labelDirection={labelDirection}
            selectMode={selecttype}
            datasoure={listData.list}
            value={valueJson}
            readonly={props.readOnly || state.disable}
            placeholder={state.placeholder ? state.placeholder : undefined}
            remove={remove}
            showField={state.showconfig?.selectName}
            type="dynamicList"
            open={openPopup}
            saveField={storageField}
            removeHtmlTag={removeHtmlTag}
          />
          <Popup
            getContainer={() => document.querySelector('.rootContainer') || document.body}
            position="bottom"
            onMaskClick={() => {
              $popupVisible(false);
              if (state.checkList && state.value) {
                $state({ ...state, checkList: state.value })
              } else {

                $state({ ...state, checkList: '' })
              }
            }}

            visible={popupVisible}
            bodyStyle={{
              height: selectWindowHeight ? selectWindowHeight + '%' : '',
              maxHeight: selectWindowHeight ? '' : '50vh',
              borderTopLeftRadius: 8,
              borderTopRightRadius: 8,
              overflow: 'hidden',
            }}
            destroyOnClose
          >
            {Popupa}
          </Popup>
        </>
    }</>
  );
});
EformDynamicList.displayName = 'EformDynamicList';
(
  EformDynamicList as typeof EformDynamicList & IDefaultValueFormat<typeof defaultProps>
).defaultValueFormat = async (props: any): Promise<string | void | string[]> => {
  const storageField = props.showconfig?.storageField || 'id';
  if (props.defaultValue && props.defaultValue.trim() !== '') {
    let arr = props.defaultValue.split(',');
    arr = arr.map((item: string) => item.trim());
    arr = arr.filter((item: string) => item !== '');
    arr = [...new Set(arr)];
    let value = arr.join(',');
    const editSourceModel = typeof props.sourceModel === 'string' ? props.sourceModel : props.sourceModel.editData;
    if (editSourceModel && value !== '') {
      let data =
        props.sourcetype === 'api'
          ? {
            appId: props.inbiz?.appInfo?.appId || '',
            id: value,
            key: editSourceModel || '',
            iConditions: {},
          }
          : {
            appId: props.inbiz?.appInfo?.appId || '',
            ids: value,
            queryKey: editSourceModel || '',
            field: storageField,
          };
      // 接口合法验证l
      const request = requestInbizData(
        () => {
          return editSourceModel;
        },
        {},
        props.inbiz
      );
      let res;
      if (typeof editSourceModel === 'object') {
        data = {
          id: value
        }
        res = await request(data)
      } else {
        res = props.sourcetype === 'api' ? await getTableInfoApi(data) : await getTableInfo(data);
      }
      if (res && !Array.isArray(res.Rows)) {
        res.Rows = [res.Rows];
      }
      if (res && Array.isArray(res.Rows) && res.Rows.length) {
        const newArr: any[] = [];
        res.UniqueId &&
          res.Rows.map((item: any) => {
            if (!item?.[storageField]) {
              item[storageField] = item?.[res.UniqueId];
            }
          });
        res.Rows.map((item: any) => {
          newArr.push(item?.[storageField]);
        });
        if (props.selecttype) {
          return newArr;
        } else if (newArr.length) {
          // 找出默认值字符串中的第一个合法值
          let list = value.split(',');
          let key = newArr?.[0];
          for (let i = 0; i < list.length; i++) {
            if (newArr.includes(list[i]) || newArr.includes(Number(list[i]))) {
              for (let j = 0; j < newArr.length; j++) {
                if (newArr?.[j] == list?.[i]) {
                  key = newArr?.[j];
                  break;
                }
              }
              break;
            }
          }
          return key;
        }
      }
    }
  }
};
// EformDynamicList.originValueFormat = (value, props) => {
//   const storageField = props.showconfig?.storageField || 'id';
//   if (props.childModelConfig && props.storageConfig) {
//     console.log(props)
//     return getChildData(props).then((res) => {
//       if (res) {
//         let modelAttr = props.storageConfig.tableData.filter(
//           (item) => item.componentAttr == storageField,
//         )[0].modelAttr;
//         if (modelAttr) {
//           let data = res?.data.map((item: any) => item[modelAttr]);
//           return data;
//         }
//       }
//     });
//   } else {
//     return value;
//   }
// };

export default connect(
  EformDynamicList,
  mapProps((props: any) => {
    const others = props;
    others.placeholder = getMessage(props.placeholder);
    return { ...others };
  }),
);
export type { Iprops };
